package com.zhangc.blog.admin.web.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhangc.blog.admin.dto.BlogDetailVO;
import com.zhangc.blog.admin.entity.BlogCommentEntity;
import com.zhangc.blog.admin.entity.BlogInfoEntity;
import com.zhangc.blog.admin.entity.BlogLinkEntity;
import com.zhangc.blog.admin.entity.BlogTagEntity;
import com.zhangc.blog.admin.entity.BlogTagRelationEntity;
import com.zhangc.blog.admin.service.BlogCommentServiceImpl;
import com.zhangc.blog.admin.service.BlogConfigServiceImpl;
import com.zhangc.blog.admin.service.BlogInfoServiceImpl;
import com.zhangc.blog.admin.service.BlogLinkServiceImpl;
import com.zhangc.blog.admin.service.BlogTagRelationServiceImpl;
import com.zhangc.blog.admin.service.BlogTagServiceImpl;
import com.zhangc.blog.admin.web.dto.AjaxPutPage;
import com.zhangc.blog.admin.web.dto.AjaxResultPage;
import com.zhangc.blog.admin.web.dto.BlogPageCondition;
import com.zhangc.blog.base.ResultBO;
import com.zhangc.blog.base.constants.LinkConstants;
import com.zhangc.blog.base.enums.BlogStatusEnum;
import com.zhangc.blog.base.enums.CommentStatusEnum;
import com.zhangc.blog.base.enums.DeleteStatusEnum;
import com.zhangc.blog.base.utils.PageResult;
import com.zhangc.blog.base.utils.QRCodeService;

/**
 * 功能描述:<br>
 *
 * @author wx:fdzhangc
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Controller
public class BlogFrontController {
    private static final Logger logger = LoggerFactory.getLogger(BlogFrontController.class);
    public static String theme = "amaze";
    @Autowired
    private BlogInfoServiceImpl blogInfoService;
    @Autowired
    private BlogTagRelationServiceImpl blogTagRelationService;
    @Autowired
    private BlogTagServiceImpl blogTagService;
    @Autowired
    private BlogConfigServiceImpl blogConfigService;
    @Autowired
    BlogCommentServiceImpl blogCommentService;

    @GetMapping({ "/", "/index", "/index.html" })
    public String index(HttpServletRequest request) {
        return this.page(request, new BlogPageCondition()
                .setPageNum(1)
                .setPageName("首页")
        );
        //return "edit";
    }

    @GetMapping({ "/pageList" })
    public String pageList(HttpServletRequest request, BlogPageCondition condition) {
        return this.page(request, condition);
    }

    private String page(HttpServletRequest request, BlogPageCondition condition) {
        if (Objects.isNull(condition.getPageNum())) {
            condition.setPageNum(1);
        }
        if (Objects.isNull(condition.getPageSize())) {
            condition.setPageSize(5);
        }
        Page<BlogInfoEntity> page = new Page<>(condition.getPageNum(), condition.getPageSize());
        LambdaQueryWrapper<BlogInfoEntity> sqlWrapper = Wrappers.<BlogInfoEntity>lambdaQuery()
                .like(Objects.nonNull(condition.getKeyword()), BlogInfoEntity::getBlogTitle, condition.getKeyword())
                .eq(Objects.nonNull(condition.getCategoryName()), BlogInfoEntity::getBlogCategoryId, condition.getCategoryName())
                .eq(BlogInfoEntity::getBlogStatus, BlogStatusEnum.RELEASE.getStatus())
                .eq(BlogInfoEntity::getIsDeleted, DeleteStatusEnum.NO_DELETED.getStatus());
        if (Objects.nonNull(condition.getTagId())) {
            List<BlogTagRelationEntity> list = blogTagRelationService.list(new QueryWrapper<BlogTagRelationEntity>()
                    .lambda().eq(BlogTagRelationEntity::getTagId, condition.getTagId()));
            if (!CollectionUtils.isEmpty(list)) {
                sqlWrapper.in(BlogInfoEntity::getBlogId, list.stream().map(BlogTagRelationEntity::getBlogId).toArray());
            } else {
                //tagid下没有文章
                sqlWrapper.in(BlogInfoEntity::getBlogId, -99L);
            }
        }
        sqlWrapper.orderByDesc(BlogInfoEntity::getCreateTime);
        blogInfoService.page(page, sqlWrapper);
        PageResult blogPageResult = new PageResult(page.getRecords(), page.getTotal(), condition.getPageSize(), condition.getPageNum());
        if (Objects.nonNull(condition.getKeyword())) {
            request.setAttribute("keyword", condition.getKeyword());
        }
        if (Objects.nonNull(condition.getTagId())) {
            request.setAttribute("tagId", condition.getTagId());
        }
        if (Objects.nonNull(condition.getCategoryName())) {
            request.setAttribute("categoryName", condition.getCategoryName());
        }
        request.setAttribute("blogPageResult", blogPageResult);
        request.setAttribute("pageName", condition.getPageName());
        request.setAttribute("newBlogs", blogInfoService.getNewBlog());
        request.setAttribute("hotBlogs", blogInfoService.getHotBlog());
        request.setAttribute("hotTags", blogTagService.getBlogTagCountForIndex());
        webKeyDescConfig(null, request);
        return "blog/" + theme + "/index";
    }

    private void webKeyDescConfig(String blogTitle, HttpServletRequest request) {
        Map<String, String> map = blogConfigService.getAllConfigs();
        map.put("websiteDescription",
                String.format("%s,%s", StringUtils.isBlank(blogTitle) ? StringUtils.EMPTY : blogTitle, map.get("websiteDescription")));
        map.put("keywords", map.get("websiteDescription"));
        request.setAttribute("configurations", map);
    }

    public static void main(String[] args) {
        String val = String.format("%s,%s", null, null);
        System.out.println(val);
    }

    @GetMapping({ "/category/{blogCategoryId}" })
    public String category(HttpServletRequest request, @PathVariable("blogCategoryId") String blogCategoryId) {
        return this.page(request, new BlogPageCondition()
                .setPageNum(1)
                .setPageName("分类")
                .setCategoryName(blogCategoryId));
    }

    @GetMapping({ "/search/{keyword}" })
    public String search(HttpServletRequest request, @PathVariable("keyword") String keyword) {
        return this.page(request, new BlogPageCondition()
                .setPageNum(1)
                .setPageName("文章搜索")
                .setKeyword(keyword)
        );
    }

    @GetMapping({ "/tag/{tagId}" })
    public String tag(HttpServletRequest request, @PathVariable("tagId") String tagId) {
        return this.page(request, new BlogPageCondition()
                .setPageNum(1)
                .setPageName("标签")
                .setTagId(tagId));
    }

    @GetMapping({ "/blogdetail/{blogId}", "/article/{blogId}" })
    public String detail(HttpServletRequest request, @PathVariable("blogId") Long blogId) {
        // 获得文章info
        BlogInfoEntity blogInfo = blogInfoService.getById(blogId);
        List<BlogTagRelationEntity> blogTagRelations = blogTagRelationService.list(new QueryWrapper<BlogTagRelationEntity>()
                .lambda()
                .eq(BlogTagRelationEntity::getBlogId, blogId));
        blogInfoService.updateById(new BlogInfoEntity()
                .setBlogId(blogInfo.getBlogId())
                .setBlogViews(blogInfo.getBlogViews() + 1));

        // 获得关联的标签列表
        List<Integer> tagIds;
        List<BlogTagEntity> tagList = new ArrayList<>();
        if (!blogTagRelations.isEmpty()) {
            tagIds = blogTagRelations.stream()
                    .map(BlogTagRelationEntity::getTagId).collect(Collectors.toList());
            tagList = blogTagService.list(new QueryWrapper<BlogTagEntity>().lambda().in(BlogTagEntity::getTagId, tagIds));
        }

        // 关联评论的Count
        Integer blogCommentCount = blogCommentService.count(new QueryWrapper<BlogCommentEntity>()
                .lambda()
                .eq(BlogCommentEntity::getCommentStatus, CommentStatusEnum.ALLOW.getStatus())
                .eq(BlogCommentEntity::getIsDeleted, DeleteStatusEnum.NO_DELETED.getStatus())
                .eq(BlogCommentEntity::getBlogId, blogId));

        BlogDetailVO blogDetailVO = new BlogDetailVO();
        BeanUtils.copyProperties(blogInfo, blogDetailVO);
        blogDetailVO.setCommentCount(blogCommentCount);
        request.setAttribute("blogDetailVO", blogDetailVO);
        request.setAttribute("tagList", tagList);
        request.setAttribute("pageName", blogInfo.getBlogTitle());
        webKeyDescConfig(blogInfo.getBlogTitle(), request);
        return "blog/" + theme + "/detail";
    }

    @GetMapping("/blog/listComment")
    @ResponseBody
    public AjaxResultPage<BlogCommentEntity> listComment(AjaxPutPage<BlogCommentEntity> ajaxPutPage, Integer blogId) {
        Page<BlogCommentEntity> page = ajaxPutPage.putPageToPage();
        blogCommentService.page(page, new QueryWrapper<BlogCommentEntity>()
                .lambda()
                .eq(BlogCommentEntity::getBlogId, blogId)
                .eq(BlogCommentEntity::getCommentStatus, CommentStatusEnum.ALLOW.getStatus())
                .eq(BlogCommentEntity::getIsDeleted, DeleteStatusEnum.NO_DELETED.getStatus())
                .orderByDesc(BlogCommentEntity::getCommentCreateTime));
        AjaxResultPage<BlogCommentEntity> ajaxResultPage = new AjaxResultPage<>();
        ajaxResultPage.setCount(page.getTotal());
        ajaxResultPage.setData(page.getRecords());
        return ajaxResultPage;
    }

    @Autowired
    private BlogLinkServiceImpl blogLinkService;

    @RequestMapping({ "/link" })
    public String link(HttpServletRequest request) {
        request.setAttribute("pageName", "友情链接");
        List<BlogLinkEntity> favoriteLinks = blogLinkService.list(new QueryWrapper<BlogLinkEntity>()
                .lambda().eq(BlogLinkEntity::getLinkType, LinkConstants.LINK_TYPE_FRIENDSHIP.getLinkTypeId())
        );
        List<BlogLinkEntity> recommendLinks = blogLinkService.list(new QueryWrapper<BlogLinkEntity>()
                .lambda().eq(BlogLinkEntity::getLinkType, LinkConstants.LINK_TYPE_RECOMMEND.getLinkTypeId())
        );
        List<BlogLinkEntity> personalLinks = blogLinkService.list(new QueryWrapper<BlogLinkEntity>()
                .lambda().eq(BlogLinkEntity::getLinkType, LinkConstants.LINK_TYPE_PRIVATE.getLinkTypeId())
        );
        //判断友链类别并封装数据 0-友链 1-推荐 2-个人网站
        request.setAttribute("favoriteLinks", favoriteLinks);
        request.setAttribute("recommendLinks", recommendLinks);
        request.setAttribute("personalLinks", personalLinks);
        //request.setAttribute("configurations", blogConfigService.getAllConfigs());
        webKeyDescConfig(null, request);
        return "blog/" + theme + "/link";
    }

    @PostMapping(value = "/blog/comment")
    @ResponseBody
    public ResultBO<String> comment(HttpServletRequest request,
            @Validated BlogCommentEntity blogComment) {
        String ref = request.getHeader("Referer");
        // 对非法字符进行转义，防止xss漏洞
        blogComment.setCommentBody(StringEscapeUtils.escapeHtml4(blogComment.getCommentBody()));
        if (StringUtils.isBlank(ref)) {
            return ResultBO.error(null, "-1", "非法请求");
        }
        boolean flag = blogCommentService.save(blogComment);
        if (flag) {
            return ResultBO.success();
        }
        return ResultBO.error(null);
    }

    @Autowired
    private QRCodeService qrCodeService;

    @GetMapping("/blog/qrImg")
    @ResponseBody
    public ResultBO<String> qrImg(String blogUrl) {
        try {
            String qrCode = qrCodeService.crateQRCode(blogUrl, 200, 200);
            return ResultBO.of(qrCode);
        } catch (IOException e) {
            logger.error("qrImg error", e);
            return ResultBO.of(null);
        }
    }
}
